﻿using System;
using System.IO;
using System.Text.RegularExpressions;
using WikiDoc.Reader;

namespace WikiDoc
{
    /// <summary>
    /// 
    /// </summary>
    public class WikiReader : TextReaderPipe
    {
        /// <summary>
        /// Initializes a new instance of the IWikiReader class.
        /// </summary>
        /// <param name="reader">The reader.</param>
        public WikiReader(TextReader reader) : base(reader)
        {
        }


        /// <summary>
        /// Reads the line and parse.
        /// </summary>
        /// <returns></returns>
        public override string ReadLine()
        {
            string line = BaseReader.ReadLine();

            if (line == null)
            {
                _CurrentLine = WikiLine.EofLine;

                return null;
            }

            _CurrentLine = GetLineInfo(line);

            return line;
        }


        private WikiLine _CurrentLine;

        /// <summary>
        /// Gets or sets the current line info.
        /// </summary>
        /// <value>The current line info.</value>
        public WikiLine CurrentLine
        {
            get { return _CurrentLine; }
        }


        private readonly ListLine _ListLine = new ListLine("dummy", LineType.NumberList, 1, 2, "dummy");
        private readonly HeaderLine _HeaderLine = new HeaderLine("dummy", 1, "dummy");
        private readonly HorizonLine _HorizonLine = new HorizonLine("dummy", 1);
        private readonly IndentLine _IndentLine = new IndentLine("dummy", 1, "dummy");
        private readonly CodeStartLine _CodeStartLine = new CodeStartLine("dummy", "dummy", "dummy");
        private readonly WikiLine _NormalLine = WikiLine.ConstructNormalLine("dummy");
        private readonly WikiLine _CodeEndLine = WikiLine.ConstructCodeEndLine("dummy");

        /// <summary>
        /// Gets the line info.
        /// </summary>
        /// <param name="line">The line.</param>
        /// <returns></returns>
        private WikiLine GetLineInfo(string line)
        {
            Match match;

            match = _blistReg.Match(line);

            if (match.Success)
            {
                return _ListLine.ResetAs(line,
                    LineType.BulletList,
                    match.Groups[1].Length,
                    match.Groups[1].Length + match.Groups[2].Length,
                    match.Groups[3].Value);
            }

            match = _nlistReg.Match(line);

            if (match.Success)
            {
                return _ListLine.ResetAs(line,
                    LineType.NumberList,
                    match.Groups[1].Length,
                    match.Groups[1].Length + match.Groups[2].Length, 
                    match.Groups[3].Value);
            }

            match = _alistReg.Match(line);

            if (match.Success)
            {
                return _ListLine.ResetAs(line,
                    LineType.AlphaList,
                    match.Groups[1].Length,
                    match.Groups[1].Length + match.Groups[2].Length,
                    match.Groups[3].Value);
            }

            match = _indentReg.Match(line);

            if (match.Success)
            {
                return _IndentLine.ResetAs(line,
                    match.Groups[1].Length,
                    match.Groups[2].Value);
            }

            match = _headerReg.Match(line);

            if (match.Success)
            {
                return _HeaderLine.ResetAs(line,
                    match.Groups[1].Length, 
                    match.Groups[2].Value);
            }

            match = _horizonReg.Match(line);

            if (match.Success)
            {
                return _HorizonLine.ResetAs(line,
                    match.Groups[1].Length);
            }

            match = _codeReg.Match(line);

            if (match.Success)
            {
                return _CodeStartLine.ResetAs(line, 
                    match.Groups[1].Value,
                    match.Groups[2].Value);
            }

            line = line.TrimEnd();
            if (line.Length == 0)
            {
                return WikiLine.EmptyLine;
            }
            else if (line == "}}}")
            {
                return _CodeEndLine.ResetAs(LineType.CodeEnd, line);
            }

            return _NormalLine.ResetAs(LineType.Normal, line);
        }

        // 代码行定义： [若干空格][{{{][至少一个空格][解析器名称][至少一个空格][解析器参数]
        private static readonly Regex _codeReg = new Regex(
            @"\A \s*  \{\{\{  (?:(?: \s+  (\S*) \s* (.*)\z)|(?: \s*\z))",
            RegexOptions.Compiled |
            RegexOptions.CultureInvariant |
            RegexOptions.Singleline |
            RegexOptions.IgnorePatternWhitespace);

        // 横线，单独的一行至少4个连续减号
        private static readonly Regex _horizonReg = new Regex(
            @"\A \s* (\-{4,}|－{4,}) \s* \z",
            RegexOptions.Compiled |
            RegexOptions.CultureInvariant |
            RegexOptions.Singleline |
            RegexOptions.IgnorePatternWhitespace);

        // 标题行定义： [若干等号][至少一个空格][标题内容][至少一个空格][若干等号]
        private static readonly Regex _headerReg = new Regex(
            @"\A \s*  ([=＝]+)(?= [^=＝])  \s*  (.*?)  \s*  (?<= [^=＝])([=＝]+) \s* \z",
            RegexOptions.Compiled |
            RegexOptions.CultureInvariant |
            RegexOptions.Singleline |
            RegexOptions.IgnorePatternWhitespace);


        // 列表行定义：[至少一个空格] [*-×—] [至少一个空格] 内容
        private static readonly Regex _blistReg = new Regex(
            @"\A (\s+)  ([*×\-—]\s+)  (.*)",
            RegexOptions.Compiled |
            RegexOptions.CultureInvariant |
            RegexOptions.Singleline |
            RegexOptions.IgnorePatternWhitespace);

        // 数字列表行定义：[至少一个空格] [数字] [.、空格][若干空格] 内容
        private static readonly Regex _nlistReg = new Regex(
            @"\A (\s+)  ([0-9]+ [\.、\s]\s*)   (.*)",
            RegexOptions.Compiled |
            RegexOptions.CultureInvariant |
            RegexOptions.Singleline |
            RegexOptions.IgnorePatternWhitespace);

        // 字母列表行定义：[至少一个空格][字母][.、空格][若干空格] 内容
        private static readonly Regex _alistReg = new Regex(
            @"\A (\s+)  ([a-zA-Z] [\.、\s]\s*)  (.*)",
            RegexOptions.Compiled |
            RegexOptions.CultureInvariant |
            RegexOptions.Singleline |
            RegexOptions.IgnorePatternWhitespace);

        // 缩进行定义：前导若干空格加若干字符
        private static readonly Regex _indentReg = new Regex(
            @"\A (\s+)  (.+)",
            RegexOptions.Compiled |
            RegexOptions.CultureInvariant |
            RegexOptions.Singleline |
            RegexOptions.IgnorePatternWhitespace);


        // WikiWord 定义：所有有效的程序类名、方法名，即大写字母开头的标志符，中间可包括句点，括号，逗号
        // 前后要求是空格，除非是行首、行尾
/*
        private static readonly Regex _wikiWordReg = new Regex(
            @" (?: \[ (?<wiki> [A-Z] [a-zA-Z0-9\._\(\),]+) \] ) " +
            @"|(?: \b (?<wiki> [A-Z] [a-zA-Z0-9\._\(\),]+) \b ) " + 
            @"",
            RegexOptions.Compiled |
            RegexOptions.CultureInvariant |
            RegexOptions.Singleline |
            RegexOptions.IgnorePatternWhitespace);
*/

//        /// <summary>
//        /// Translates the wiki word.
//        /// </summary>
//        /// <param name="str">The STR.</param>
//        /// <returns></returns>
//        public static string TranslateWikiWord(string str)
//        {
//            //return _wikiWordReg.Replace(str, )
//            return str;
//        }
    }

}
